/*
 * Copyright 2011 es-planning Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jp.arctos.ursus.extension.net;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Service base class.
 * 
 */
abstract class Service {

    /** Selector handler. */
    SelectorHandler selectorHandler;

    /** Shutdown status of service. */
	AtomicBoolean isShutdowned = new AtomicBoolean(false);

    /** Service / Session configuration. */
    Config config;

    /** State for inhibiting session generation. */
    AtomicBoolean isSessionCreated = new AtomicBoolean(false);

    /** Collection of generated sessions. */
    Collection<Session> sessions;

    /**
     * Constructor.
     * 
     * @param config Configuration
     * @throws IOException 
     */
    Service(Config config) throws IOException {
        this.config = config;

        sessions = new ConcurrentLinkedQueue<Session>();
        selectorHandler = new SelectorHandler(this);
        selectorHandler.open(config.getRealtimeThreadParameters());
    }
    
    /**
     * Received "session close". // TODO
     * 
     * @param session Session
     */
    abstract void sessionClosed(Session session);

    /**
     * Shutdown the service.
     * This process will be blocked from other threads if already underway.
     * 
     */
    public synchronized void shutdown() {
        if (isShutdowned.getAndSet(true)) return;
        doShutdown();
    }

    /**
     * Shutdown.
     * 
     */
    abstract void doShutdown();
	
    /**
     * Accepting connections by selection.
     * 
     * @param key Selection key
     */
    void onAcceptable(SelectionKey key) {}

    /**
     * Accepting connections by selection.
     * 
     * @param key　Selection key
     */
    void onConnectable(SelectionKey key) {}

    /**
     * Readable by selection.
     * 
     * @param key　Selection key
     */
    void onReadable(SelectionKey key) {}

    /**
     * An error occurred during selection.
     * 
     * @param reason Error reason
     */
    void onSelectionError(Exception reason) {}

    /**
     * Writable by selection.
     * 
     * @param key Selection key
     */
    void onWritable(SelectionKey key) {}
}
